#! /usr/bin/env python
"""
::BOH
$Id: owtf-lite.py,v 1.0 2007/04/22 00:00:00

Copyright (c) 2007 George Bobeck. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
::EOH

OWTF-Lite Client.
"""

import sys, os 
try:
    import ownet
    from OWTFparser import *
except:
    sys.exit(1)
import signal
import thread
import threading
from time import *
from datetime import *
from Queue import *
from socket import *

storage_q = Queue()
init = HandleXML()
config = ConfScanner(init.ParseFromFile("lite-configuration.conf"))

remote_server = config.remote[0]
remote_port = config.remote[1]
buf = 1024
addr = (remote_server,remote_port)
UDPSock = socket( AF_INET,SOCK_DGRAM )

# to send something, use the following:
#
# UDPSock.sendto( data2,addr )

resolution = int(config.resolution)
if config.collector_host.strip() == "localhost":
    OWFShost = ""
else:
    OWFShost = config.collector_host.strip()

OWFSport = config.collector_port

def signal_handler(signal,frame):
    UDPSock.close()
    sys.exit( 0 )

def GenSensorDict(l):
    d = {}
    for x in l:
        d[x[0]] = x[1]
    return d

def owtfMonitor(var_host = "", var_port = 4304):
    r = ownet.Sensor('/', server = var_host, port = int(var_port))
    e = r.entryList()
    s = r.sensorList()

    global storage_q
    global config
    sensor_dict = GenSensorDict(config.sensors)
    
    for x in r.sensors():
        reading = Reading()
        tm = datetime.today().strftime( "%Y-%m-%d %H:%M:%S" ) # YYYY-MM-DD HH:MM:SS  
        try:
            reading.SetAlias(sensor_dict[x.address])
        except:
            reading.SetAlias("None")
        try:
            reading.SetLocation(config.collector_alias)
        except:
            reading.SetLocation("None")
        reading.SetTime(datetime.today().strftime( "%Y-%m-%d %H:%M:%S" )) 
        reading.SetSID(x.address)
        reading.SetMID(config.collector_alias)
        #to be removed
        #print tm, x.address
        
        if hasattr(x, 'MultiSensor'):
            try:
                #print x.MultiSensor
                reading.SetMultiSensor(x.MultiSensor)
            except:
                pass
        if hasattr(x,"type"):
            try:
                #print x.type
                reading.SetType(x.type)
            except:
                pass
        if hasattr(x, 'temperature'):
            # -40 C -> +85 C
            try:
                if float(x.temperature) >= -40 and float(x.temperature) <= 85:
                    #print x, x.temperature, ((1.8 * x.temperature)+32)
                    reading.SetTemp(x.temperature)
                else:
                    pass
            except:
                pass

        if hasattr(x, 'humidity'):
            # 0% - 100%
            try:
                if float(x.humidity) >= 0.0 and float(x.humidity) <= 100:
                    #print x, x.humidity
                    reading.SetHumid(x.humidity)
                else:
                    pass
            except:
                pass

        if hasattr(x, 'VAD'):
            # 1.5 V - 10 V
            try:
                if float(x.VAD) >= 1.5 and float(x.VAD) <= 10:
                    reading.SetV1(x.VAD)
                else:
                    pass
            except:
                pass

        if hasattr(x, 'VDD'):
            # 2.4 V - 10 V
            try:
                if float(x.VDD) >= 2.4 and float(x.VAD) <= 10:
                    reading.SetV2(x.VDD)
                else:
                    pass
            except:
                pass
        storage_q.put(reading)

def Sender(q, sock, address):
    if not q.empty():
        x = q.get()
        sock.sendto( x.toXML(),address )
    else:
        pass

class SenderThread(threading.Thread):
    def __init__(self, queue, sock, address):
        self.queue = queue
        self.sock = sock
        self.address = address
        threading.Thread.__init__(self)
    def run(self):
        while(1):
            Sender(self.queue, self.sock, self.address)

class CollectorThread(threading.Thread):
    def __init__(self, server, port, resolution):
        self.server = server
        self.port = port
        self.delay = int(resolution)
        threading.Thread.__init__(self)
    def run(self):
        while(1):
            owtfMonitor(self.server, self.port)
            sleep(self.delay)

thread1 = CollectorThread(OWFShost, OWFSport, config.resolution)
thread2 = SenderThread(storage_q, UDPSock, addr)

signal.signal(signal.SIGINT, signal_handler)

thread1.start()
thread2.start()

